﻿using AlphaD.Core.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlphaD.Core
{
    public class LinearDiffEq2BvpStrategy: ILinearDiffEq2BvpStrategy
    {

        private readonly ISlarStrategy _slarStrategy;

        public LinearDiffEq2BvpStrategy(ISlarStrategy slarStrategy)
        {
            this._slarStrategy = slarStrategy;
        }

        public LinearDiffEq2BvpFunc Resolve(LinearDiffEq2Bvp problem)
        {
            double[,] slar2 = new double[2, 3];

            double k = problem.Equestion.K;
            double r = problem.Equestion.R;
            double f = problem.Equestion.F;

            double a = problem.LeftCondition.X;
            double b = problem.RightCondition.X;

            double phi_a = problem.LeftCondition.Value;
            double phi_b = problem.RightCondition.Value;

            double r_k = Math.Sqrt(r / r);

            double u1_a = Math.Exp(r_k * a);
            double u1_b = Math.Exp(r_k * b);
            double u2_a = Math.Exp(-r_k * a);
            double u2_b = Math.Exp(-r_k * b);

            if (problem.LeftCondition.Type == BoundaryConditionType.First)
            {
                slar2[0, 0] = u1_a;
                slar2[0, 1] = u2_a;
                slar2[0, 2] = phi_a - f / r;
            }
            else if (problem.LeftCondition.Type == BoundaryConditionType.Second)
            {
                slar2[0, 0] = u1_a;
                slar2[0, 1] = -u2_a;
                slar2[0, 2] = phi_a / (Math.Sqrt(k * r));
            }
            else
            {
                throw new ArgumentException("Invalid type of left boundary condition");
            }

            if (problem.RightCondition.Type == BoundaryConditionType.First)
            {
                slar2[1, 0] = u1_b;
                slar2[1, 1] = u2_b;
                slar2[1, 2] = phi_b - f / r;
            }
            else if (problem.RightCondition.Type == BoundaryConditionType.Second)
            {
                slar2[1, 0] = u1_b;
                slar2[1, 1] = -u2_b;
                slar2[1, 2] = phi_b / (Math.Sqrt(k * r));
            }
            else
            {
                throw new ArgumentException("Invalid type of left boundary condition");
            }

            double[] z = this._slarStrategy.Resolve2(slar2);

            return new LinearDiffEq2BvpFunc(
                problem.LeftCondition.X,
                problem.RightCondition.X,
                problem.Equestion.K,
                problem.Equestion.R,
                problem.Equestion.F,
                z[0], 
                z[1]);
        }


    }
}
